package userlogic

import (
	"context"

	"go-zero-admin/apps/system/cmd/rpc/internal/logic/userpost"
	"go-zero-admin/apps/system/cmd/rpc/internal/svc"
	"go-zero-admin/apps/system/cmd/rpc/syspb"
	"go-zero-admin/apps/system/model"
	"go-zero-admin/pkg/tool"
	"go-zero-admin/pkg/xerr"

	"github.com/duke-git/lancet/v2/convertor"
	"github.com/duke-git/lancet/v2/slice"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/fx"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

type DelUserLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
	getUserPostListLogic *userpostlogic.GetUserPostListLogic
}

func NewDelUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DelUserLogic {
	return &DelUserLogic{
		ctx:                  ctx,
		svcCtx:               svcCtx,
		Logger:               logx.WithContext(ctx),
		getUserPostListLogic: userpostlogic.NewGetUserPostListLogic(ctx, svcCtx),
	}
}

func (l *DelUserLogic) DelUser(in *syspb.DelUserReq) (*syspb.DelUserResp, error) {
	if len(in.GetIds()) == 0 || in.GetCurrentUserId() == 0 || (!in.GetIsDel() && in.GetUpdateUser() == "") {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除用户失败：参数缺失"),
			tool.GetErrMsgFormat("delete config"), "params is not existed", in)
	}

	// 判断是否删除自己
	if slice.Contain(in.GetIds(), in.GetCurrentUserId()) {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除用户失败：当前用户不能删除"),
			tool.GetErrMsgFormat("delete user"), "myself not delete myself", in)
	}

	// 判断是否是超级管理员
	uidList := l.svcCtx.Config.SystemCustom.NotCheckAuthUserIds
	for _, v := range in.GetIds() {
		if slice.Contain(uidList, v) {
			return nil, errors.Wrapf(xerr.NewErrMsg("删除用户失败：不允许操作超级管理员"),
				tool.GetErrMsgFormat("delete user"), "user is admin", in)
		}
	}

	// 删除
	if err := l.svcCtx.SysUserModel.Trans(l.ctx, func(context context.Context, session sqlx.Session) error {
		e := l.svcCtx.SysUserModel.DeleteEx(l.ctx, session, in.GetIds(), in.GetIsDel(), in.GetUpdateUser())
		if e != nil {
			return e
		}

		// 删除对应权限
		enforcer := l.svcCtx.AdapterCasbin.SetCtxSession(l.ctx, session).Enforcer
		for _, v := range in.GetIds() {
			// 删除用户与岗位关联
			userPostListResp, e := l.getUserPostListLogic.GetUserPostList(&syspb.GetUserPostListReq{
				UserId: v,
			})
			if e != nil {
				return e
			}
			if len(userPostListResp.GetList()) > 0 {
				var idList []int64
				fx.From(func(source chan<- interface{}) {
					for _, v := range userPostListResp.GetList() {
						source <- v
					}
				}).Map(func(item interface{}) interface{} {
					return item.(*syspb.SysUserPost).Id
				}).ForEach(func(item interface{}) {
					idList = append(idList, item.(int64))
				})
				e = l.svcCtx.SysUserPostModel.DeleteEx(l.ctx, session, idList, true, "")
				if e != nil {
					return e
				}
			}

			// 删除用户与角色关联
			if _, e = enforcer.RemoveFilteredGroupingPolicy(0, convertor.ToString(v)); e != nil {
				return e
			}
		}

		return nil
	}); err != nil {
		return nil, errors.Wrapf(xerr.NewErrFindOneCode(err, model.ErrNotFound),
			tool.GetErrMsgFormat("delete user"), err, in)
	}

	return &syspb.DelUserResp{}, nil
}
